//
//  CWViewController.m
//  CWDevelop
//
//  Created by LittoCats on 7/9/14.
//  Copyright (c) 2014 Littocats. All rights reserved.
//

#import "CWViewController.h"
#import "CWCore.h"

#import <objc/objc-runtime.h>

#define kCWViewControllerNameKey @"kCWViewControllerNameKey"

@interface CWViewController ()

@property (nonatomic, strong) NSMutableDictionary *params;

@property (nonatomic, strong) CWJavaScriptContext *jsContext;

@end

@implementation CWViewController

- (id)initWithIdentifier:(NSString *)identifier params:(NSDictionary *)params
{
    self = [super init];
    if (self) {
        // Custom initialization
        self.params = [NSMutableDictionary dictionaryWithDictionary:params];
//        NSString *type = [[identifier componentsSeparatedByString:@"/"] lastObject];
        
//        NSString *currentPath = [NSString stringWithFormat:@"%@/%@",[CWFile appRootPath],type];
        NSString *currentPath = params[@"__path"];
        NSString *script = [params[@"script"] isKindOfClass:[NSString class]] && ![params[@"script"] isEmpty] ? params[@"script"] : [[currentPath componentsSeparatedByString:@"/"] lastObject];
        
        [_params addEntriesFromDictionary:@{@"__identifier":identifier,
                                            @"__script": script,}];
        [self.params setObject:identifier forKey:kCWViewControllerNameKey];
        self.jsContext = [CWJavaScriptContext context];
        
        NSString *scriptPath = [script hasPrefix:@"/"] ? script :
                               [script hasPrefix:@"./"] ? [NSString stringWithFormat:@"%@/%@.js",currentPath,[script substringFromIndex:2]] :
                               [NSString stringWithFormat:@"%@/%@.js",currentPath, script];
        
        NSString *jsString = [NSString stringWithContentsOfFile:scriptPath
                                                       encoding:NSUTF8StringEncoding error:nil];
        jsString = [NSString stringWithFormat:@"var _page = \"%@\";var __path = \"%@\"; %@",
                    self._id,
                    currentPath,
                    jsString ? jsString : @""];
        [_jsContext evaluateScript:jsString];
        
        //记录
        [CWViewControllers() setObject:self forKey:identifier];
    }
    return self;
}

- (void)loadView
{
    NSMutableDictionary *JSONLayout;
    if (![_params[@"layout"] isKindOfClass:[NSDictionary class]]) {

        NSString *layoutName = _params[@"layout"] && ![_params[@"layout"] isEmpty]? _params[@"layout"] : [[_params[@"__path"] componentsSeparatedByString:@"/"] lastObject];
        NSString *JSONLayoutFilePath = [NSString stringWithFormat:@"%@/%@.json",_params[@"__path"],layoutName];
        NSData *JSONLayoutData = [NSData dataWithContentsOfFile:JSONLayoutFilePath];
        JSONLayout = JSONLayoutData ? [NSJSONSerialization JSONObjectWithData:JSONLayoutData
                                                                      options:NSJSONReadingMutableContainers
                                                                        error:nil]
                                    : [NSMutableDictionary new];
    }else{
        JSONLayout = _params[@"layout"];
    }
    [JSONLayout setObject:self.jsContext._id forKey:@"___context"];
    self.view = [UIView instanceWithJSONLayout:JSONLayout];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    if (ISIOS7ORLATER) {
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.extendedLayoutIncludesOpaqueBars = YES;
        self.automaticallyAdjustsScrollViewInsets = NO;
    }
    [self.params[[NSString stringWithFormat:@"__onCreated_%p",[self _id]]] evaluateWithArguments:self._id, nil];
    
    [self analyzeNavigationBarItem];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:[self.params[@"hideActionBar"] boolValue] animated:YES];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.params[[NSString stringWithFormat:@"__onResume_%p",[self _id]]] evaluateWithArguments:self._id, nil];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    [self.params[[NSString stringWithFormat:@"__onPause_%p",[self _id]]] evaluateWithArguments:self._id, nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark- anaylze navigationBarItem
- (void)analyzeNavigationBarItem
{
    NSMutableDictionary *navigationBarItemAttributes = self.params[@"actionBar"];
    for (NSString *itemAttr in [navigationBarItemAttributes allKeys]) {
        objc_msgSend(self,
                     NSSelectorFromString([NSString stringWithFormat:@"analyze%@:",[itemAttr capitalizedString]]),
                     navigationBarItemAttributes[itemAttr]);
    }
}
- (void)analyzeTitle:(id)titleAttributes
{
    if ([titleAttributes isKindOfClass:[NSString class]]) {
        self.navigationItem.title = titleAttributes;
    }else if ([titleAttributes isKindOfClass:[NSMutableDictionary class]]){
        [titleAttributes setObject:self.jsContext._id forKey:@"_contextId"];
        self.navigationItem.titleView = [UIView instanceWithJSONLayout:titleAttributes];
    }
}
- (void)analyzeLeftitem:(id)leftItemAttributes
{
    if ([leftItemAttributes isKindOfClass:[NSMutableDictionary class]]) {
        [leftItemAttributes setObject:self.jsContext._id forKey:@"_contextId"];
        self.navigationItem.leftBarButtonItem = [[CWBarButtonItem alloc] initWithAttributes:leftItemAttributes];
    }else if ([leftItemAttributes isKindOfClass:[NSArray class]]){
        NSMutableArray *items = [NSMutableArray new];
        for (NSMutableDictionary *itemAttribute in leftItemAttributes) {
            if ([itemAttribute isKindOfClass:[NSMutableDictionary class]]) continue;
            [itemAttribute setObject:self.jsContext._id forKey:@"_contextId"];
            [items addObject:[[CWBarButtonItem alloc] initWithAttributes:itemAttribute]];
        }
        self.navigationItem.leftBarButtonItems = items;
    }
}
- (void)analyzeRightitem:(id)rightItemAttributes
{
    if ([rightItemAttributes isKindOfClass:[NSMutableDictionary class]]) {
        [rightItemAttributes setObject:self.jsContext._id forKey:@"_contextId"];
        self.navigationItem.leftBarButtonItem = [[CWBarButtonItem alloc] initWithAttributes:rightItemAttributes];
    }else if ([rightItemAttributes isKindOfClass:[NSArray class]]){
        NSMutableArray *items = [NSMutableArray new];
        for (NSMutableDictionary *itemAttribute in rightItemAttributes) {
            if ([itemAttribute isKindOfClass:[NSMutableDictionary class]]) continue;
            [itemAttribute setObject:self.jsContext._id forKey:@"_contextId"];
            [items addObject:[[CWBarButtonItem alloc] initWithAttributes:itemAttribute]];
        }
        self.navigationItem.rightBarButtonItems = items;
    }
}

#pragma mark- utilies

+ (instancetype)controllerWithId:(NSString *)pageId
{
    CWViewController *vc = [CWViewControllers() objectForKey:pageId];
    if (!vc)
        vc = [NSObject findInstanceWithId:pageId];
    
    return vc;
}

static NSMapTable *CWViewControllers()
{
    static NSMapTable *table = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        table = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsWeakMemory valueOptions:NSPointerFunctionsWeakMemory capacity:16];
    });
    return table;
}
@end

@implementation UINavigationController (CW)

+ (instancetype)defaultNavigationController
{
    return (UINavigationController *)kKeyWindow.rootViewController;
}

+ (void)pushViewController:(UIViewController *)vc asRoot:(BOOL)asRoot
{
    UINavigationController *nav = [self defaultNavigationController];
    if (!nav || asRoot) {
        nav = [[UINavigationController alloc] init];
        kKeyWindow.rootViewController = nav;
        [kKeyWindow makeKeyAndVisible];
        [nav pushViewController:vc animated:NO];
    }else if ([nav.viewControllers containsObject:vc]){
        [nav popToViewController:vc animated:YES];
    }else{
        [nav pushViewController:vc animated:YES];
    }
}

@end

CWJavaScriptContext *app_jsContext_CW(){
    static CWJavaScriptContext *jsContext = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        jsContext = [CWJavaScriptContext context];
    });
    return jsContext;
}

void app_startRunning(NSDictionary *launchOptions)
{
    NSString *appJavaScript = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"main" ofType:@".js"]
                                                        encoding:NSUTF8StringEncoding
                                                           error:nil];
    [app_jsContext_CW() evaluateScript:appJavaScript ? appJavaScript : @""];
}